package me.zhengjie.wcs;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.Log;
import me.zhengjie.domain.InventoryService;
import me.zhengjie.domain.TaskResultService;
import me.zhengjie.dto.Request;
import me.zhengjie.dto.Response;
import me.zhengjie.dto.sqlServer.*;
import me.zhengjie.repository.*;
import me.zhengjie.service.OutBoundOrderService;
import me.zhengjie.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "WCS上报信息")
@RequestMapping("/api/wcsReport")
public class WcsReport {

    private final DeviceStatusRepository deviceStatusRepository;
    private final TaskResultRepository taskResultRepository;
    private final InBoundMissionHistoryRepository inBoundMissionHistoryRepository;
    private final OutBoundMissionHistoryRepository outBoundMissionHistoryRepository;
    private final StorageService storageService;
    private final ObjectMapper objectMapper;
    private final PalletRepository palletRepository;
    private final ProcesscardRepository processcardRepository;
    private final InventoryRepository inventoryRepository;
    private final TaskResultService taskResultService;
    private final InventoryService inventoryService;
    private final OutBoundMissionRepository outBoundMissionRepository;
    private final OutBoundOrderDetailRepository outBoundOrderDetailRepository;
    private final OutBoundOrderRepository outBoundOrderRepository;
    private final OutBoundOrderService outBoundOrderService;

    private static final Logger reportLog = LoggerFactory.getLogger("report");

    @PostMapping(value = "/deviceStatus")
    @Log("码垛机状态")
    @ApiOperation("码垛机状态")
    @Transactional
    public Response getDeviceStatus(@RequestBody Request request){
        try {
            Object object = request.getData();
            if (!ObjectUtil.isEmpty(object)){

                /*DeviceStatus deviceStatus = (DeviceStatus)object;*/
                DeviceStatus deviceStatus = objectMapper.convertValue(object, DeviceStatus.class);
                reportLog.info("接受到设备状态数据:{}",deviceStatus);

                String code = deviceStatus.getCode();

                DeviceStatus oldDeviceStatus = deviceStatusRepository.findOldDeviceStatus(code);
                log.info("查找到的旧码垛机状态信息：{}",oldDeviceStatus);
                if (ObjectUtil.isEmpty(oldDeviceStatus)){
                    deviceStatusRepository.save(deviceStatus);
                    /*deviceStatusRepository.saveNewStatus(deviceStatus.getCode(),deviceStatus.getEquipmentType(),deviceStatus.getAisle(),deviceStatus.getLayer(),deviceStatus.getStatus());*/
                }else {
                    deviceStatusRepository.updateDeviceStatus(deviceStatus.getAisle(),deviceStatus.getLayer(),deviceStatus.getStatus(), deviceStatus.getLastUpdated(),code);
                }
                return new Response(request.getMessageId(),1,"");
            }else {
                return new Response(request.getMessageId(),0,"获取码垛机状态失败");
            }
        } catch (Exception e) {
            log.error("码垛机状态获取失败，失败原因：{}", e.toString());
            return new Response(request.getMessageId(),0,"获取码垛机状态失败");
        }
    }


    /**
     * 接收当前的任务状态，记录历史出入库任务
     * @param request 请求体
     * @return Response 响应体
     */
    @PostMapping(value = "/taskResult")
    @Log("任务状态")
    @ApiOperation("任务状态")
    @Transactional
    public Response getTaskResult(@RequestBody Request request){
        try {
            Object object = request.getData();
            if (!ObjectUtil.isEmpty(object)){
                TaskResult data = objectMapper.convertValue(object, TaskResult.class);
                reportLog.info("接收到的任务状态信息：{}",data);
                String wmsTaskId = data.getWmsTaskId();
                TaskResult taskResult = taskResultRepository.findTaskResultByWmsTaskId(wmsTaskId);
                if (ObjectUtil.isEmpty(taskResult)){
                    // 获取失败
                    return new Response(request.getMessageId(),0,"获取任务状态失败");
                }else {
                    log.info("查询到的该条任务之前的状态：{}",taskResult);
                    taskResultRepository.updateTaskResult(data.getFromLocation(), data.getToLocation(), data.getStatus(), data.getLastUpdated(), wmsTaskId);
                    // 判断任务类型，保存出库入库的完成时间

                    Integer taskType = data.getWcsTaskType();
                    // 入库任务
                    if (taskType == 1){

                        if (data.getStatus() == 2){
                            log.info("收到入库任务反馈，开始更新历史任务，储位，以及库存");
                            // 任务结束记录
                            int inBoundMissionHistoryResult = inBoundMissionHistoryRepository.updateFinishTime(DateTime.now().toTimestamp(), String.valueOf(data.getWmsTaskId()), "任务完成");
                            log.info("更新的历史入库任务条数：{}",inBoundMissionHistoryResult);
                            // 释放储位
                            String storageCode = taskResult.getToLocation();
                            int storageResult = storageService.openStorage(storageCode);
                            log.info("更新的储位条数：{}",storageResult);

                            // 入库信息补全
                            String palletCode = data.getLpnCode();
                            Pallet pallet = palletRepository.findPalletByPalletCode(palletCode);
                            log.error("载盘已进入库区，当前载盘：{}",pallet);
                            Integer processCardId = pallet.getProcesscardId();
                            Processcard processcard = processcardRepository.findProcesscardById(processCardId);
                            Storage storage = storageService.findStorageByStorageCode(storageCode);

                            // 入库存
                            Inventory inventory = new Inventory();
                            inventory.setWorkNum(processcard.getWorkNum());
                            inventory.setBatch(processcard.getProcesscardCode());
                            // 入库完成时间
                            inventory.setInBoundFinishTime(DateTime.now().toTimestamp());
                            inventory.setInventoryStatus(1);
                            inventory.setStorageId(storage.getId());
                            inventory.setPalletId(pallet.getId());
                            inventory.setProcesscardId(processcard.getId());
                            log.info("载盘已进入库区，更新库存信息：{}",inventory);
                            inventoryRepository.save(inventory);
                            // 更新储位的信息
                            storageService.finishInBound(pallet.getId(),storageCode);
                            taskResultService.deleteByWmsTaskId(data.getWmsTaskId());
                        }
                    // 出库任务
                    }else if (taskType == 2){

                        if (data.getStatus() == 2){
                            // 查询出库单
                            String missionCode = String.valueOf(data.getWmsTaskId());
                            Integer orderId = outBoundMissionRepository.findOutBoundMissionByMissionCode(missionCode).getOutBoundOrderId();


                            /*List<OutBoundOrderDetail> details = outBoundOrderDetailRepository.findOutBoundOrderDetailsByOutBoundOrderId(orderId);
                            List<Integer> detailPalletIds = details.stream().map(OutBoundOrderDetail::getPalletId).collect(Collectors.toList());
                            log.info("查询到的出库明细单中的载盘id:{}",detailPalletIds);
                            String workNum = outBoundOrder.getWorkNum();
                            List<Inventory> inventories = inventoryRepository.findInventoriesByWorkNum(workNum);
                            log.info("查询到的该出库单工程号对应的库存：{}",inventories);*/

                            List<OutBoundMission> outBoundMissions = outBoundMissionRepository.findOutBoundMissionsByOutBoundOrderId(orderId);

                            if (outBoundMissions.size()==1){
                                log.info("出库单：{}{}",orderId,"结束！");
                                outBoundOrderService.finishOrder(orderId);
                            }

                            /*List<Integer> inventoryPalletIds = inventories.stream().map(Inventory::getPalletId).collect(Collectors.toList());
                            int count = Math.toIntExact(detailPalletIds.stream()
                                    .filter(inventoryPalletIds::contains)
                                    .count());
                            if (count == 1){

                                outBoundOrderService.finishOrder(orderId);
                            }*/

                            // 任务结束记录
                            outBoundMissionHistoryRepository.updateFinishTime(DateTime.now().toTimestamp(), String.valueOf(data.getWmsTaskId()),"任务完成");
                            // 释放储位
                            storageService.cleanStorage(data.getFromLocation());

                            // 删除库存
                            Pallet pallet = palletRepository.findPalletByPalletCode(taskResult.getLpnCode());
                            Integer palletId = pallet.getId();

                            // 删除任务，库存，任务状态
                            outBoundMissionRepository.deleteOutBoundMissionByMissionCode(String.valueOf(missionCode));
                            inventoryService.deleteByPalletId(palletId);
                            taskResultService.deleteByWmsTaskId(data.getWmsTaskId());
                        }
                    }
                }
                return new Response(request.getMessageId(),1,"");
            } else {
                // 获取失败
                return new Response(request.getMessageId(),0,"获取任务状态失败");
            }
        } catch (Exception e) {
            log.error("获取任务状态失败，失败原因：{}", e.toString());
            // 获取失败
            return new Response(request.getMessageId(),0,"获取任务状态失败");
        }
    }

}
